﻿// ===============================================================================
// XCI.Parent 西安交通信息WinForm开发框架 2019 版权所有
// ===============================================================================

using System;
using System.ComponentModel;
using XCI.Helper;
using XCI.Windows.Helper;

namespace XCI.Windows
{
    /// <summary>
    /// 封装BackgroundWorker异步组件
    /// </summary>
    public class AsyncWorker: IDisposable
    {
        private readonly BackgroundWorker _worker;
        private Action<DoWorkEventArgs> _runAction;
        private Action<ProgressChangedEventArgs> _progressAction;
        private Func<RunWorkerCompletedEventArgs, bool> _cancelAction;
        private Action<RunWorkerCompletedEventArgs> _errorAction;
        private Action<RunWorkerCompletedEventArgs> _completAction;

        /// <summary>
        /// 初始化BackgroundWorker异步组件
        /// </summary>
        public AsyncWorker() : this(false, false)
        {
        }

        /// <summary>
        /// 初始化BackgroundWorker异步组件
        /// </summary>
        /// <param name="reportsProgress">获取或设置一个值，该值指示是否 System.ComponentModel.BackgroundWorker 可以报告进度更新。</param>
        /// <param name="supportsCancellation">获取或设置一个值，该值指示是否 System.ComponentModel.BackgroundWorker 支持异步取消操作。</param>
        public AsyncWorker(bool reportsProgress, bool supportsCancellation)
        {
            _worker = new BackgroundWorker();
            _worker.WorkerReportsProgress = reportsProgress;
            _worker.WorkerSupportsCancellation = supportsCancellation;
            _worker.DoWork += Worker_DoWork;
            _worker.ProgressChanged += Worker_ProgressChanged;
            _worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        }

        /// <summary>
        /// 获取线程执行对象。
        /// </summary>
        public BackgroundWorker Worker => _worker;

        /// <summary>
        /// 获取一个值，该值指示应用程序是否已请求取消后台操作。
        /// </summary>
        public bool CancellationPending => _worker.CancellationPending;

        /// <summary>
        /// 获取一个值，该值指示是否 System.ComponentModel.BackgroundWorker 正在运行的异步操作。
        /// </summary>
        public bool IsBusy => _worker.IsBusy;

        /// <summary>
        /// 设置异步执行回调函数
        /// </summary>
        /// <param name="runAction">回调函数</param>
        public AsyncWorker RunCallback(Action<DoWorkEventArgs> runAction)
        {
            _runAction = runAction;
            return this;
        }

        /// <summary>
        /// 设置进度变化回调函数
        /// </summary>
        /// <param name="progressAction">回调函数</param>
        public AsyncWorker ProgressCallback(Action<ProgressChangedEventArgs> progressAction)
        {
            _progressAction = progressAction;
            return this;
        }

        /// <summary>
        /// 设置后台操作取消回调函数。
        /// </summary>
        /// <param name="cancelAction">回调函数</param>
        public AsyncWorker CancelCallback(Func<RunWorkerCompletedEventArgs, bool> cancelAction)
        {
            _cancelAction = cancelAction;
            return this;
        }

        /// <summary>
        /// 设置后台操作异常回调函数。
        /// </summary>
        /// <param name="errorAction">回调函数</param>
        public AsyncWorker ErrorCallback(Action<RunWorkerCompletedEventArgs> errorAction)
        {
            _errorAction = errorAction;
            return this;
        }

        /// <summary>
        /// 设置后台操作已完成、 已取消或引发异常时回调函数。
        /// </summary>
        /// <param name="completAction">回调函数</param>
        public AsyncWorker CompletCallback(Action<RunWorkerCompletedEventArgs> completAction)
        {
            _completAction = completAction;
            return this;
        }

        /// <summary>
        /// 开始执行后台操作。
        /// </summary>
        public void RunAsync()
        {
            if (_worker.IsBusy)
            {
                return;
            }
            _worker.RunWorkerAsync();
        }

        ///// <summary>
        ///// 开始执行后台操作。
        ///// </summary>
        ///// <param name="argument">使用后台操作以在中执行的参数 System.ComponentModel.BackgroundWorker.DoWork 事件处理程序。</param>
        //public void RunAsync(object argument)
        //{
        //    _worker.RunWorkerAsync(argument);
        //}

        /// <summary>
        /// 请求取消的挂起的后台操作。
        /// </summary>
        public void CancelAsync()
        {
            _worker.CancelAsync();
        }

        /// <summary>
        /// 引发 System.ComponentModel.BackgroundWorker.ProgressChanged 事件。
        /// </summary>
        /// <param name="percentProgress"> 从 0 到 100 的后台操作已完成百分比。</param>
        public void ReportProgress(int percentProgress)
        {
            _worker.ReportProgress(percentProgress);
        }


        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            _runAction?.Invoke(e);
        }

        private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            _progressAction?.Invoke(e);
        }

        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                var r = _cancelAction?.Invoke(e);
                if (r.HasValue && r.Value == false)
                {
                    return;
                }
            }
            if (e.Error != null)
            {
                if (_errorAction != null)
                {
                    _errorAction?.Invoke(e);
                }
                else
                {
                    MessageBoxHelper.ShowError(DebugHelper.BuildAllMessage(e.Error));
                    //throw e.Error;
                }
            }
            else
            {
                _completAction?.Invoke(e);
            }
        }

        public void Dispose()
        {
            _worker.Dispose();
        }
    }
}